package cn.xingzhen.jfield.ui;

import cn.xingzhen.jfield.helper.StringHelper;
import cn.xingzhen.jfield.helper.ValidUtil;

import java.sql.Connection;
import java.util.List;
import java.util.Map;

/**
 * @author xingzhen [2023-03-17 11:58]
 * @since
 */
public abstract class DataField {

    private MainFrame frame;

    public DataField(MainFrame frame) {
        this.frame = frame;
    }

    public MainFrame getFrame() {
        return frame;
    }

    abstract public Connection getConnection();

    abstract public Map<String, List<String>> getColumnTypes();

    abstract public List<FieldAttr> getColumns() throws Exception;

    abstract public void close();


    private String testField(String fieldName) {
        if (getFrame().tuoFeng.isSelected()) {
            return StringHelper.humpString(fieldName);
        }
        if (getFrame().xiaoXie.isSelected()) {
            return fieldName.toLowerCase();
        }
        return fieldName;
    }

    public StringBuilder javaField() throws Exception {
        if (getFrame().riQi.isSelected()) {
            ValidUtil.notEmpty(getFrame().rqFormat, "日期格式不能为空");
        }
        StringBuilder sb = new StringBuilder();
        List<FieldAttr> list = this.getColumns();
        String temp;
        FieldAttr column;
        int size = list.size();
        for (int i = 0; i < size; i++) {
            column = list.get(i);
            if (getFrame().jfNotNull.isSelected()) {
                if (column.isNullable()) continue;
            }
            // 非空注解
            if (getFrame().feiKong.isSelected()) {
                StringBuilder stringBuilder = null;
                if (getFrame().fkWithDB.isSelected()) {
                    if (!column.isNullable()) {
                        stringBuilder = this.addNotNull(column);
                    }
                } else {
                    stringBuilder = this.addNotNull(column);
                }
                if (stringBuilder != null && stringBuilder.length() != 0) {
                    sb.append(stringBuilder).append(ToolConfigure.NL);
                }
            }
            // 长度注解
            if (getFrame().changDu.isSelected()) {
                StringBuilder stringBuilder = this.addLength(column);
                if (stringBuilder.length() != 0) {
                    sb.append(stringBuilder).append(ToolConfigure.NL);
                }
            }
            // 日期注解
            if (getFrame().riQi.isSelected()) {
                StringBuilder stringBuilder = this.addDateFormat(column);
                if (stringBuilder.length() != 0) {
                    sb.append(stringBuilder).append(ToolConfigure.NL);
                }
            }
            // Java代码
            if (getFrame().beiZhu.isSelected()) {
                temp = String.format(ToolConfigure.FORMAT_JAVA_FIELD, asJavaField(column.getType()),
                                     testField(column.getName()),
                                     StringHelper.isEmpty(column.getComment()) ? "" : column.getComment(),
                                     column.getName(), column.getType(), column.getMaxLength(), column.getPrecision(),
                                     "null(" + column.isNullable() + ")");
            } else {
                temp = String.format(ToolConfigure.FORMAT_JAVA_FIELD2, asJavaField(column.getType()),
                                     testField(column.getName()));
            }
            sb.append(temp);
            if (i != size - 1) {
                sb.append(ToolConfigure.NL);
            }
        }
        return sb;
    }

    private String asJavaField(String columnType) {
        String fieldType;
        switch (columnType.toLowerCase()) {
            case "tinyint":
            case "smallint":
            case "mediumint":
                fieldType = "Integer";
                break;
            case "int":
            case "integer":
                fieldType = "Integer";
                break;
            case "bigint":
                fieldType = "Long";
                break;
            case "time":
                fieldType = "Time";
                break;
            case "double":
            case "real":
                fieldType = "Double";
                break;
            case "decimal":
            case "numeric":
            case "smallmoney":
            case "money":
            case "number":
                fieldType = "BigDecimal";
                break;
            case "float":
                fieldType = "Float";
                break;
            case "date":
            case "year":
                fieldType = getFrame().jfDateString.isSelected() ? "String" : "Date";
                break;
            case "smalldatetime":
            case "datetime":
            case "timestamp":
                fieldType = getFrame().jfDateString.isSelected() ? "String" : "Timestamp";
                break;
            case "bit": //用于存储布尔值，只占1位，取值 0（false） 或 1（true）
                fieldType = "Boolean";
                break;
            case "clob":
            case "nclob":
            case "blob":// 65K
            case "mediumblob":// 16M
            case "longblob": // 4G
            case "binary":
            case "varbinary":
            case "image":
                fieldType = "byte[]";
                break;
            //case "set" :
            //case "enum" :
            //case "char" :
            //case "varchar" :
            //case "tinytext" :
            //case "text" :
            //case "mediumtext" ://16M
            //case "longtext" :
            default:
                fieldType = "String";
        }
        return fieldType;
    }

    private StringBuilder addNotNull(FieldAttr column) {
        StringBuilder sb = new StringBuilder();
        sb.append("@");
        String notnull = getFrame().fkType.getSelectedItem().toString();
        sb.append(notnull);
        if (getFrame().fkMessage.isSelected()) {
            sb.append("(message=\"");
            sb.append("[").append(column.getName()).append("]不能为空");
            /*
            if (StringHelper.isNotEmpty(column.getComment())) {
                sb.append(column.getComment());
            } else {
                if (StringHelper.isNotEmpty(column.getComment())) {
                    sb.append(column.getComment()).append(", 不能为空");
                } else {
                    sb.append(column.getName()).append(" 不能为空");
                }
            }*/
            sb.append("\")");
        }
        return sb;
    }

    private StringBuilder addLength(FieldAttr column) {
        List<String> size = this.getColumnTypes().get(ToolConfigure.$Size);
        List<String> max = this.getColumnTypes().get(ToolConfigure.$Max);
        List<String> decimal = this.getColumnTypes().get(ToolConfigure.$Decimal);
        StringBuilder sb = new StringBuilder();
        if (column.getMaxLength() == null || column.getMaxLength() == 0) {
            return sb;
        }
        if (column.getMaxLength() == -1) {
            sb.append("//长度无限制");
            return sb;
        }
        if (size.contains(column.getType())) {
            if (getFrame().feiKong.isSelected()) {
                sb.append("@Size(min = 1, max = ");
            } else {
                sb.append("@Size(max = ");
            }
            int len = column.getMaxLength();
            len = charLength(len);
            sb.append(len);
            sb.append(", message = \"");
            sb.append("长度要求在 1~").append(len).append("之间");
            sb.append("\")");
        } else if (max.contains(column.getType())) {
            //@Max(value = 88, message = "最大值为88") // 最大值88
            sb.append("@Max(value = ");
            int len = column.getMaxLength() - column.getPrecision();
            len = charLength(len);
            long maxNum = this.maxNum(len);
            sb.append(maxNum);
            sb.append(", message = \"");
            sb.append("最大值为").append(maxNum);
            sb.append("\")");
        } else if (decimal.contains(column.getType())) {
            //@DecimalMin(value = "0.1") // 最小值0.1元
            //@DecimalMax(value = "10000.00") // 最大值10000元
            int len = column.getMaxLength() - column.getPrecision();
            len = charLength(len);
            if (getFrame().feiKong.isSelected()) {
                if (column.getPrecision() != 0) {
                    sb.append("@DecimalMin(value =\"");
                    sb.append(minDecimal(column.getPrecision()));
                    sb.append("\")").append(ToolConfigure.NL);
                }
            }
            sb.append("@DecimalMax(value = \"");
            sb.append(maxNum(len));
            sb.append("\")");
        }
        return sb;
    }

    private int charLength(int len) {
        if(getFrame().cdChinese.isSelected()) {
            int l = len / 3; // 默认按UTF-8编码截取
            if(l <= 0) {
                return 1;
            } else {
               return l;
            }
        }
        return len;
    }

    private String minDecimal(int len) {
        String tmp = "0.";
        for (int i = 1; i < len; i++) {
            tmp += "0";
        }
        return tmp += "1";
    }

    private long maxNum(int len) {
        String tmp = "";
        for (int i = 0; i < len; i++) {
            tmp += "9";
        }
        return Long.parseLong(tmp);
    }

    private StringBuilder addDateFormat(FieldAttr column) {
        StringBuilder sb = new StringBuilder();
        List<String> date = this.getColumnTypes().get(ToolConfigure.$Date);
        if (date.contains(column.getType())) {
            //@DateTimeFormat(pattern = "yyyy-MM-dd") // 日期格式化转换
            String temp = "@DateTimeFormat(pattern = \"%s\")";
            if (StringHelper.isNotEmpty(getFrame().rqFormat.getText())) {
                sb.append(String.format(temp, getFrame().rqFormat.getText()));
            } else {
                sb.append(String.format(temp, "yyyy-MM-dd HH:mm:ss"));
            }
        }
        return sb;
    }

    //sql select 部分
    public StringBuilder sqlSelectField() throws Exception {
        StringBuilder sb = new StringBuilder();
        List<FieldAttr> list = this.getColumns();
        int size = list.size();
        FieldAttr column;
        for (int i = 0; i < size; i++) {
            //column = list.get(i);
            //sb.append(column.getName());
            //if (i != size - 1) {
            //    sb.append(",").append(ToolConfigure.NL);
            //}
            column = list.get(i);
            if (StringHelper.isNotEmpty(getFrame().tableAsName.getText())) {
                sb.append(getFrame().tableAsName.getText()).append(".");
            }
            sb.append(column.getName());
            if (getFrame().tuoFeng.isSelected()) {
                sb.append(" as ");
                sb.append(StringHelper.humpString(column.getName()));
            } else if (getFrame().xiaoXie.isSelected()) {
                sb.append(" as ");
                sb.append(column.getName().toLowerCase());
            }
            if (i != size - 1) {
                sb.append(", ");
            }
            if (getFrame().beiZhu.isSelected() && StringHelper.isNotEmpty(column.getComment())) {
                sb.append("/*");
                sb.append(column.getComment());
                sb.append("*/");
            }
            sb.append(ToolConfigure.NL);
        }
        return sb;
    }

    // sql 插入
    public StringBuilder sqlInsert() throws Exception {
        StringBuilder sb = new StringBuilder();
        List<FieldAttr> list = this.getColumns();
        int size = list.size();
        FieldAttr column;
        sb.append("insert ").append("into ");
        sb.append(getFrame().tableName.getText()).append("(");
        StringBuilder sb2 = new StringBuilder();
        for (int i = 0; i < size; i++) {
            column = list.get(i);
            sb.append(column.getName());
            sb2.append("?");
            if (i != size - 1) {
                sb.append(",");
                sb2.append(",");
            }
        }
        sb.append(")").append(" ").append("values(");
        sb.append(sb2).append(")");
        return sb;
    }

    // sql 删除
    public StringBuilder sqlDelete() {
        StringBuilder sb = new StringBuilder();
        sb.append("delete from ").append(getFrame().tableName.getText()).append(" ");
        sb.append("where ");
        return sb;
    }

    // sql 修改
    public StringBuilder sqlUpdate() throws Exception {
        StringBuilder sb = new StringBuilder();
        sb.append("update ").append(getFrame().tableName.getText()).append(" ");
        sb.append("set ");
        List<FieldAttr> list = this.getColumns();
        int size = list.size();
        FieldAttr column;
        for (int i = 0; i < size; i++) {
            column = list.get(i);
            sb.append(column.getName()).append("=?");
            if (i != size - 1) {
                sb.append(", ").append(ToolConfigure.NL);
            }
        }
        sb.append(" where ");
        return sb;
    }

    // sql 查询
    public StringBuilder sqlSelect() throws Exception {
        StringBuilder sb = new StringBuilder();
        sb.append("select ").append(ToolConfigure.NL);
        sb.append(sqlSelectField());
        sb.append("from ").append(getFrame().tableName.getText()).append(" ").append(getFrame().tableAsName.getText());
        return sb;
    }

    // MyBaits
    public StringBuilder mbInsert() throws Exception {
        StringBuilder sb = new StringBuilder();
        List<FieldAttr> list = this.getColumns();
        int size = list.size();
        FieldAttr column;
        sb.append("insert ").append("into ");
        sb.append(getFrame().tableName.getText()).append("(").append(ToolConfigure.NL);
        StringBuilder sb2 = new StringBuilder();
        for (int i = 0; i < size; i++) {
            column = list.get(i);
            sb.append(column.getName());
            sb2.append(String.format(ToolConfigure.FORMAT_MYBATIS_INSERT, testField(column.getName())));
            if (i != size - 1) {
                sb.append(",");
                sb2.append(",");
                sb.append(ToolConfigure.NL);
                sb2.append(ToolConfigure.NL);
            }
        }
        sb.append(") ").append("values(").append(ToolConfigure.NL);
        sb.append(sb2).append(")");
        return sb;
    }

    public StringBuilder mbUpdate() throws Exception {
        StringBuilder sb = new StringBuilder();
        List<FieldAttr> list = this.getColumns();
        int size = list.size();
        FieldAttr column;
        sb.append("update ").append(getFrame().tableName.getText()).append(ToolConfigure.NL).append("<set>").append(
                ToolConfigure.NL);
        for (int i = 0; i < size; i++) {
            column = list.get(i);
            sb.append(String.format(ToolConfigure.FORMAT_MYBATIS_UPDATE, testField(column.getName()), column.getName(),
                                    testField(column.getName())));
            sb.append(ToolConfigure.NL);
        }
        sb.append("</set>");
        return sb;
    }

    public StringBuilder mbUpdateSet() throws Exception {
        StringBuilder sb = new StringBuilder();
        List<FieldAttr> list = this.getColumns();
        int size = list.size();
        FieldAttr column;
        for (int i = 0; i < size; i++) {
            column = list.get(i);
            sb.append(String.format(ToolConfigure.FORMAT_MYBATIS_UPDATE, testField(column.getName()), column.getName(),
                                    testField(column.getName())));
            sb.append(ToolConfigure.NL);
        }
        return sb;
    }
}
